# -*- coding: utf-8 -*-

###############################################################################
# Name: __init__.py                                                           #
# Purpose: Extended IPythonShell Plugin                                       #
# Author: Minjae Kim <the.minjae_at_gmail.com>                                #
# Test Release                                                                #
###############################################################################


# Original IPythonShell Plugin Information
###############################################################################
# Name: __init__.py                                                           #
# Purpose: IPythonShell Plugin                                                #
# Author: Laurent Dufréchou <laurent.dufrechou@gmail.com>                     #
# Copyright: (c) 2008 Laurent Dufréchou                                       #
# License: wxWindows License                                                  #
###############################################################################

# Plugin Metadata
"""Extended IPython Shell"""
__author__ = "Minjae Kim"
__version__ = "0.0.4"



#-----------------------------------------------------------------------------#
# Imports

import wx
import sys
import re
import iface
import plugin

import profiler

#used for ipython GUI objects
from ipythonmod.gui.wx.ipython_view import IPShellWidget
from ipythonmod.gui.wx.ipython_history import IPythonHistoryPanel

# for making ipython quick launch menu
from ed_menu import EdMenuBar

# custom module
from xpyshell import config


#-----------------------------------------------------------------------------#
# Globals
_ = wx.GetTranslation
ID_RUN_IPYTHON  = wx.NewId()        #for menu IPython: run in ipython
ID_DBG_IPYTHON  = wx.NewId()        #for menu IPython: debug in ipython
ID_CLR_IPYTHON  = wx.NewId()        #for menu IPython: clear ipython screen
#-----------------------------------------------------------------------------#
# Interface Implementation
class xPyShell(plugin.Plugin):
    
    """Adds menu items"""
    def PlugIt(self, parent):
        """Implements MainWindowI's PlugIt Method"""
        self._mw = parent
        
        # bindings for menu items
        binding_run = u"\t"+u"F5"
        binding_dbg = u"\t"+u"F4"
        binding_clr = u"\t"+u"Alt+C"
        EdMenuBar.keybinder.SetBinding(ID_RUN_IPYTHON, binding_run)
        EdMenuBar.keybinder.SetBinding(ID_DBG_IPYTHON, binding_dbg)
        EdMenuBar.keybinder.SetBinding(ID_CLR_IPYTHON, binding_clr)
        
        # add menu items
        #em = self._mw.GetMenuBar().GetMenuByName("tools")
        self.ipy_menu = wx.Menu()
        self.ipy_menu.Insert(0, ID_RUN_IPYTHON, _("&Run in iPython")+\
                        EdMenuBar.keybinder.GetBinding(ID_RUN_IPYTHON),
                        _("Run the current file in iPython"))
        self.ipy_menu.Insert(1, ID_DBG_IPYTHON, _("&Debug in iPython")+\
                        EdMenuBar.keybinder.GetBinding(ID_DBG_IPYTHON),
                        _("Debug the current file in iPython"))
        
        self.ipy_menu.Insert(2, ID_CLR_IPYTHON, _("&Clear screen")+\
                        EdMenuBar.keybinder.GetBinding(ID_CLR_IPYTHON),
                        _("Clear the iPython shell screen"))
        
        menubar = self._mw.GetMenuBar()
        menubar.Append(self.ipy_menu, '&IPython')
        
        # disable the menu initially
        self.ipy_menu.Enable(ID_RUN_IPYTHON, False)
        self.ipy_menu.Enable(ID_DBG_IPYTHON, False)

        
    def GetMenuHandlers(self):
        """Returns the event handler for this plugins menu entry"""
        return [(ID_RUN_IPYTHON, self.OnRuniPython), (ID_DBG_IPYTHON, self.OnDebugiPython),
            (ID_CLR_IPYTHON, self.OnClearScreen)]

    
    def OnDebugiPython(self, evt):
        """Debug the file in ipython shell"""
        
        # save stc control for current and future external uses
        notebook = self._mw.GetNotebook()
        config.ed_stc = notebook.GetCurrentCtrl()
        
               
        # collect bookmarks
        bmlist = config.ed_stc.GetBookmarks()
        
#        # for future breakpoints, make margin wider
#        config.ed_stc.SetMarginWidth(0,20)
        
        # automated debugger input
        self.ipython_panel.IP.dbginput = []
        self.ipython_panel.IP.dbginput.append('s')
        if bmlist:
            for bkpoint in bmlist:
                self.ipython_panel.IP.dbginput.append('break '+str(bkpoint+1))
        
        
        # run the file in ipython
        filepath = config.ed_stc.GetFileName()
        self.ipython_panel.text_ctrl.write('%run -d '+filepath)
        self.ipython_panel.stateDoExecuteLine()
    
    def OnRuniPython(self, evt):
        """Run the file in ipython shell"""
        
        # save stc control for current and future external uses
        notebook = self._mw.GetNotebook()
        config.ed_stc = notebook.GetCurrentCtrl()
        
        # run the file in ipython
        filepath = config.ed_stc.GetFileName()
        self.ipython_panel.text_ctrl.write('%run '+filepath)
        self.ipython_panel.stateDoExecuteLine()
        
    def OnClearScreen(self, evt):
        """Clears the ipython shell screen"""         
        config.ipy_stc.ClearAll()
        config.ipy_stc.showPrompt()
        
    
    """Adds a PyShell to the Shelf"""
    plugin.Implements(iface.ShelfI, iface.MainWindowI)
    ID_IPYSHELL = wx.NewId()

    __name__ = u'xPyShell'

    def AllowMultiple(self):
        """IPythonShell allows multiple instances"""
        return True

    def OptionSave(self,key,value):
        profiler.Profile_Set('IPython.'+key, value)
        
    def CreateItem(self, parent):
                     
        
        """Returns an IPythonShell Panel"""
        self._log = wx.GetApp().GetLog()
        self._log("[xPyShell][info] Creating IPythonShell instance for Shelf")
        #main_win = wx.GetApp().GetMainWindow()
        #parent.AddPage(self.history_panel,'IPythonHistory',False)
        
        splitter = wx.SplitterWindow(parent, -1, style = wx.SP_LIVE_UPDATE)
        
        self.history_panel    = IPythonHistoryPanel(splitter)
        self.history_panel.setOptionTrackerHook(self.OptionSave)
        
        self.ipython_panel    = IPShellWidget(splitter, background_color="BLACK")
                                              #user_ns=locals(),user_global_ns=globals(),)
        self.ipython_panel.setOptionTrackerHook(self.OptionSave)
        self.ipython_panel.setHistoryTrackerHook(self.history_panel.write)
        
        options_ipython = self.ipython_panel.getOptions()
        for key in options_ipython.keys():
            saved_value = profiler.Profile_Get('IPython.'+key)
            if saved_value is not None:
                options_ipython[key]['value'] = saved_value

        options_history = self.history_panel.getOptions()
        for key in options_history.keys():
            saved_value = profiler.Profile_Get('IPython.'+key)
            if saved_value is not None:
                options_history[key]['value'] = saved_value
        
        self.ipython_panel.reloadOptions(options_ipython)
        self.history_panel.reloadOptions(options_history)


        splitter.SetMinimumPaneSize(20)
        splitter.SplitVertically(self.ipython_panel, self.history_panel, -100)
        #splitter.SplitVertically(frame, self.history_panel, -100)
        
        ### for better split window sizing behavior
        self._splitter = splitter
        shell_window = splitter.GetWindow1()
        shell_window.SetMinSize((500,0))
      
        history_window = splitter.GetWindow2()
        history_window.SetMinSize((100,0))
        
        splitter.SetSashGravity(0.7)
        
        # enable menu items
        self.ipy_menu.Enable(ID_RUN_IPYTHON, True)
        self.ipy_menu.Enable(ID_DBG_IPYTHON, True)
     
        return splitter


    def GetId(self):
        return xPyShell.ID_IPYSHELL

    def GetMenuEntry(self, menu):
        return wx.MenuItem(menu, xPyShell.ID_IPYSHELL,
                           xPyShell.__name__, 
                           _("Open an IPython Shell"))

    def GetName(self):
        return xPyShell.__name__

    def IsStockable(self):
        return True
